import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import type { PayloadAction } from '@reduxjs/toolkit';
import type {
  Project,
  Task,
  TaskGroup,
  ProjectState,
  FilterOptions,
  SortOptions
} from '../types/project';
import { mockProjectApi } from '../api/mockProjectApi';

/**
 * 项目管理状态的初始值
 * 定义了 Redux store 中项目模块的默认状态
 */
const initialState: ProjectState = {
  /** 所有项目的列表数据 */
  projects: [],
  /** 当前选中/正在查看的项目 */
  currentProject: null,
  /** 全局加载状态，用于显示 loading 效果 */
  loading: false,
  /** 错误信息，用于显示错误提示 */
  error: null,
  /** 当前应用的筛选条件（状态、优先级、负责人等） */
  filters: {},
  /** 当前的排序设置 */
  sort: {
    field: 'createdAt',    // 默认按创建时间排序
    order: 'desc',         // 默认降序（最新的在前面）
  },
  /** 视图模式：'my_created'(我创建的) | 'my_participated'(我参与的) */
  viewMode: 'my_created',
};

/**
 * ===== 异步 Thunk Actions =====
 * 这些函数用于处理异步操作，如 API 调用
 * Redux Toolkit 的 createAsyncThunk 会自动生成 pending/fulfilled/rejected 状态
 */

/**
 * 获取所有项目列表
 * 用于：项目管理主页面初始化时加载所有项目
 * 触发时机：页面首次加载、刷新项目列表
 */
export const fetchProjects = createAsyncThunk(
  'project/fetchProjects',
  async () => {
    return await mockProjectApi.getProjects();
  }
);

/**
 * 获取单个项目的详细信息
 * 用于：点击进入具体项目时加载项目详情和任务数据
 * 触发时机：切换项目、进入项目详情页
 * @param projectId - 项目的唯一标识符
 */
export const fetchProject = createAsyncThunk(
  'project/fetchProject',
  async (projectId: string) => {
    return await mockProjectApi.getProject(projectId);
  }
);

/**
 * 创建新项目
 * 用于：用户点击"新建项目"按钮时创建项目
 * 触发时机：新建项目表单提交
 * @param projectData - 新项目的基本信息（标题、描述等）
 */
export const createProject = createAsyncThunk(
  'project/createProject',
  async (projectData: Partial<Project>) => {
    return await mockProjectApi.createProject(projectData);
  }
);

/**
 * 更新项目信息
 * 用于：修改项目的基本信息（标题、描述、成员等）
 * 触发时机：项目设置页面保存、项目信息编辑
 * @param projectId - 要更新的项目ID
 * @param data - 要更新的项目数据
 */
export const updateProject = createAsyncThunk(
  'project/updateProject',
  async ({ projectId, data }: { projectId: string; data: Partial<Project> }) => {
    return await mockProjectApi.updateProject(projectId, data);
  }
);

/**
 * 创建新任务
 * 用于：用户在任务看板中点击"添加任务"或"新建任务"按钮
 * 触发时机：新建任务表单提交
 * @param projectId - 所属项目ID
 * @param groupId - 任务要放入的分组ID（如：待开始、进行中等）
 * @param taskData - 新任务的详细信息（标题、描述、负责人、截止时间等）
 */
export const createTask = createAsyncThunk(
  'project/createTask',
  async ({ projectId, groupId, taskData }: {
    projectId: string;
    groupId: string;
    taskData: Partial<Task>
  }) => {
    return await mockProjectApi.createTask(projectId, groupId, taskData);
  }
);

/**
 * 更新任务信息
 * 用于：编辑任务详情、修改任务状态、更新子任务等
 * 触发时机：任务详情弹窗保存、状态切换、进度更新
 * @param projectId - 所属项目ID
 * @param taskId - 要更新的任务ID
 * @param data - 要更新的任务数据（可以是部分字段）
 */
export const updateTask = createAsyncThunk(
  'project/updateTask',
  async ({ projectId, taskId, data }: {
    projectId: string;
    taskId: string;
    data: Partial<Task>
  }) => {
    return await mockProjectApi.updateTask(projectId, taskId, data);
  }
);

/**
 * 删除任务
 * 用于：用户在任务操作菜单中选择删除
 * 触发时机：确认删除任务后
 * @param projectId - 所属项目ID
 * @param taskId - 要删除的任务ID
 * @returns 返回被删除的任务信息，用于状态更新
 */
export const deleteTask = createAsyncThunk(
  'project/deleteTask',
  async ({ projectId, taskId }: { projectId: string; taskId: string }) => {
    await mockProjectApi.deleteTask(projectId, taskId);
    return { projectId, taskId };
  }
);

/**
 * 移动任务到不同分组
 * 用于：拖拽任务卡片在看板中移动（跨分组或同分组内重新排序）
 * 触发时机：拖拽操作完成后的服务器同步
 * @param projectId - 所属项目ID
 * @param taskId - 要移动的任务ID
 * @param sourceGroupId - 原始分组ID
 * @param targetGroupId - 目标分组ID
 * @param targetIndex - 在目标分组中的位置索引
 */
export const moveTask = createAsyncThunk(
  'project/moveTask',
  async ({
    projectId,
    taskId,
    sourceGroupId,
    targetGroupId,
    targetIndex
  }: {
    projectId: string;
    taskId: string;
    sourceGroupId: string;
    targetGroupId: string;
    targetIndex: number;
  }) => {
    return await mockProjectApi.moveTask(projectId, taskId, sourceGroupId, targetGroupId, targetIndex);
  }
);

/**
 * 创建新的任务分组
 * 用于：用户在看板中添加新的任务分组（如：待验收、已暂停等）
 * 触发时机：点击"添加分组"按钮并填写分组信息后
 * @param projectId - 所属项目ID
 * @param groupData - 新分组的信息（标题、颜色、排序等）
 */
export const createGroup = createAsyncThunk(
  'project/createGroup',
  async ({ projectId, groupData }: { projectId: string; groupData: Partial<TaskGroup> }) => {
    return await mockProjectApi.createGroup(projectId, groupData);
  }
);

/**
 * 更新任务分组信息
 * 用于：修改分组名称、颜色、排序顺序等
 * 触发时机：分组设置弹窗保存、拖拽调整分组顺序
 * @param projectId - 所属项目ID
 * @param groupId - 要更新的分组ID
 * @param data - 要更新的分组数据
 */
export const updateGroup = createAsyncThunk(
  'project/updateGroup',
  async ({ projectId, groupId, data }: {
    projectId: string;
    groupId: string;
    data: Partial<TaskGroup>
  }) => {
    return await mockProjectApi.updateGroup(projectId, groupId, data);
  }
);

/**
 * 删除任务分组
 * 用于：用户删除不需要的分组（分组内的任务会被移动到其他分组）
 * 触发时机：确认删除分组操作后
 * @param projectId - 所属项目ID
 * @param groupId - 要删除的分组ID
 * @returns 返回被删除的分组信息，用于状态更新
 */
export const deleteGroup = createAsyncThunk(
  'project/deleteGroup',
  async ({ projectId, groupId }: { projectId: string; groupId: string }) => {
    await mockProjectApi.deleteGroup(projectId, groupId);
    return { projectId, groupId };
  }
);

/**
 * ===== Redux Slice 定义 =====
 * 包含同步的 reducers 和异步操作的处理逻辑
 */
const projectSlice = createSlice({
  name: 'project',
  initialState,
  /**
   * ===== 同步 Reducers =====
   * 这些函数用于直接修改状态，不涉及异步操作
   */
  reducers: {
    /**
     * 设置筛选条件
     * 用于：用户在筛选器中选择筛选条件（状态、优先级、负责人等）
     * 触发时机：筛选器组件中的选择操作
     * @param action.payload - 新的筛选条件（会与现有条件合并）
     */
    setFilters: (state, action: PayloadAction<FilterOptions>) => {
      state.filters = { ...state.filters, ...action.payload };
    },

    /**
     * 设置排序方式
     * 用于：用户选择不同的排序字段和排序方向
     * 触发时机：点击排序按钮或下拉选择排序方式
     * @param action.payload - 新的排序设置（字段和升序/降序）
     */
    setSort: (state, action: PayloadAction<SortOptions>) => {
      state.sort = action.payload;
    },

    /**
     * 切换视图模式
     * 用于：在"我创建的"和"我参与的"任务视图之间切换
     * 触发时机：点击页面顶部的视图切换标签
     * @param action.payload - 新的视图模式
     */
    setViewMode: (state, action: PayloadAction<'my_created' | 'my_participated'>) => {
      state.viewMode = action.payload;
    },

    /**
     * 清除错误信息
     * 用于：用户关闭错误提示后清除错误状态
     * 触发时机：点击错误提示的关闭按钮
     */
    clearError: (state) => {
      state.error = null;
    },

    /**
     * 本地更新任务状态（用于实时操作的乐观更新）
     * 用于：在等待服务器响应期间立即更新 UI，提升用户体验
     * 触发时机：任务状态修改、进度更新等操作前的预处理
     * @param action.payload.taskId - 要更新的任务ID
     * @param action.payload.updates - 要更新的任务字段
     */
    updateTaskLocal: (state, action: PayloadAction<{ taskId: string; updates: Partial<Task> }>) => {
      if (state.currentProject) {
        const task = state.currentProject.groups
          .flatMap(group => group.tasks)
          .find(task => task.id === action.payload.taskId);
        if (task) {
          Object.assign(task, action.payload.updates);
        }
      }
    },

    /**
     * 本地移动任务（用于拖拽操作的乐观更新）
     * 用于：拖拽任务时立即更新 UI，无需等待服务器响应
     * 触发时机：拖拽操作完成时，在发送服务器请求前先更新本地状态
     * 注意：这是乐观更新，如果服务器操作失败需要回滚
     * @param action.payload.taskId - 要移动的任务ID
     * @param action.payload.sourceGroupId - 原始分组ID
     * @param action.payload.targetGroupId - 目标分组ID
     * @param action.payload.targetIndex - 在目标分组中的位置
     */
    moveTaskLocal: (state, action: PayloadAction<{
      taskId: string;
      sourceGroupId: string;
      targetGroupId: string;
      targetIndex: number;
    }>) => {
      try {
        if (state.currentProject) {
          const { taskId, sourceGroupId, targetGroupId, targetIndex } = action.payload;

          console.log('moveTaskLocal 开始执行:', action.payload);

          const sourceGroup = state.currentProject.groups.find(g => g.id === sourceGroupId);
          const targetGroup = state.currentProject.groups.find(g => g.id === targetGroupId);

          if (!sourceGroup) {
            console.error('源分组未找到:', sourceGroupId);
            return;
          }

          if (!targetGroup) {
            console.error('目标分组未找到:', targetGroupId);
            return;
          }

          const taskIndex = sourceGroup.tasks.findIndex(t => t.id === taskId);
          if (taskIndex === -1) {
            console.error('任务未找到:', taskId, '在分组:', sourceGroupId);
            return;
          }

          // 验证目标索引
          if (targetIndex < 0 || targetIndex > targetGroup.tasks.length) {
            console.error('无效的目标索引:', targetIndex, '最大允许索引:', targetGroup.tasks.length);
            return;
          }

          // 获取要移动的任务
          const task = sourceGroup.tasks[taskIndex];

          console.log('找到要移动的任务:', task.title, '从索引:', taskIndex, '到索引:', targetIndex);

          // 使用函数式方法重建数组，避免直接修改 Immer 代理
          const updatedTask = { ...task, groupId: targetGroupId };

          if (sourceGroupId === targetGroupId) {
            // 同组内移动：重新排序
            console.log('同组内移动');

            // 创建不包含移动任务的数组
            const tasksWithoutMoved = sourceGroup.tasks.filter(t => t.id !== taskId);

            // 调整目标索引：如果向后移动，需要减1（因为移除了源任务）
            const adjustedTargetIndex = targetIndex > taskIndex ? targetIndex - 1 : targetIndex;

            console.log('索引调整:', { 原始目标索引: targetIndex, 调整后索引: adjustedTargetIndex, 源索引: taskIndex });

            // 在指定位置插入任务
            const newTasks = [
              ...tasksWithoutMoved.slice(0, adjustedTargetIndex),
              updatedTask,
              ...tasksWithoutMoved.slice(adjustedTargetIndex)
            ];

            sourceGroup.tasks = newTasks;
          } else {
            // 跨组移动
            console.log('跨组移动');

            // 从源分组移除任务
            sourceGroup.tasks = sourceGroup.tasks.filter(t => t.id !== taskId);

            // 在目标分组的指定位置插入任务
            const newTargetTasks = [
              ...targetGroup.tasks.slice(0, targetIndex),
              updatedTask,
              ...targetGroup.tasks.slice(targetIndex)
            ];

            targetGroup.tasks = newTargetTasks;
          }

          console.log('moveTaskLocal 执行成功');
        }
      } catch (error) {
        console.error('moveTaskLocal 执行失败:', error);
      }
    },
  },
  /**
   * ===== 异步操作的状态处理 =====
   * extraReducers 用于处理 createAsyncThunk 生成的异步 action
   * 每个异步操作都有 pending（进行中）、fulfilled（成功）、rejected（失败）三个状态
   */
  extraReducers: (builder) => {
    builder
      /**
       * 获取项目列表的状态处理
       */
      // 开始获取项目列表 - 显示加载状态
      .addCase(fetchProjects.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      // 获取项目列表成功 - 更新项目数据，隐藏加载状态
      .addCase(fetchProjects.fulfilled, (state, action) => {
        state.loading = false;
        state.projects = action.payload;
      })
      // 获取项目列表失败 - 显示错误信息，隐藏加载状态
      .addCase(fetchProjects.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message || 'Failed to fetch projects';
      })

      /**
       * 获取单个项目详情的状态处理
       */
      // 开始获取项目详情 - 显示加载状态
      .addCase(fetchProject.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      // 获取项目详情成功 - 设置当前项目，隐藏加载状态
      .addCase(fetchProject.fulfilled, (state, action) => {
        state.loading = false;
        state.currentProject = action.payload;
      })
      // 获取项目详情失败 - 显示错误信息，隐藏加载状态
      .addCase(fetchProject.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message || 'Failed to fetch project';
      })

      /**
       * 创建项目成功的状态处理
       * 将新创建的项目添加到项目列表中
       */
      .addCase(createProject.fulfilled, (state, action) => {

        state.projects.push(action.payload);
      })

      /**
       * 更新项目成功的状态处理
       * 同时更新项目列表和当前项目（如果是同一个项目）
       */
      .addCase(updateProject.fulfilled, (state, action) => {
        // 更新项目列表中的项目
        const index = state.projects.findIndex(p => p.id === action.payload.id);
        if (index !== -1) {
          state.projects[index] = action.payload;
        }
        // 如果更新的是当前项目，也要更新当前项目的数据
        if (state.currentProject?.id === action.payload.id) {
          state.currentProject = action.payload;
        }
      })

      /**
       * 创建任务成功的状态处理
       * 将新任务添加到指定分组中
       */
      .addCase(createTask.fulfilled, (state, action) => {
        // 更新当前项目
        if (state.currentProject) {
          const group = state.currentProject.groups.find(g => g.id === action.payload.groupId);
          if (group) {
            group.tasks.push(action.payload);
          }
        }
        // 同步更新项目列表中的对应项目
        const projectIdArg = (action.meta as any)?.arg?.projectId as string | undefined;
        if (projectIdArg) {
          const proj = state.projects.find(p => p.id === projectIdArg);
          if (proj) {
            const g = proj.groups.find(gr => gr.id === action.payload.groupId);
            if (g) {
              g.tasks.push(action.payload);
            }
          }
        }
      })

      /**
       * 创建任务失败的状态处理
       */
      .addCase(createTask.rejected, (state, action) => {
        console.error('创建任务失败:', action.error);
        state.error = action.error.message || 'Failed to create task';
      })

      /**
       * 更新任务成功的状态处理
       * 找到对应的任务并更新其数据
       */
      .addCase(updateTask.fulfilled, (state, action) => {
        // 当前项目
        if (state.currentProject) {
          const task = state.currentProject.groups
            .flatMap(group => group.tasks)
            .find(task => task.id === action.payload.id);
          if (task) {
            Object.assign(task, action.payload);
          }
        }
        // 项目列表
        const projectIdArg = (action.meta as any)?.arg?.projectId as string | undefined;
        if (projectIdArg) {
          const proj = state.projects.find(p => p.id === projectIdArg);
          if (proj) {
            for (const gr of proj.groups) {
              const idx = gr.tasks.findIndex(t => t.id === action.payload.id);
              if (idx !== -1) {
                gr.tasks[idx] = action.payload;
                break;
              }
            }
          }
        }
      })

      /**
       * 删除任务成功的状态处理
       * 从所有分组中移除指定的任务
       */
      .addCase(deleteTask.fulfilled, (state, action) => {
        if (state.currentProject) {
          state.currentProject.groups.forEach(group => {
            const taskIndex = group.tasks.findIndex(t => t.id === action.payload.taskId);
            if (taskIndex !== -1) {
              group.tasks.splice(taskIndex, 1);
            }
          });
        }
        // 同步更新项目列表
        const proj = state.projects.find(p => p.id === action.payload.projectId);
        if (proj) {
          proj.groups.forEach(group => {
            const taskIndex = group.tasks.findIndex(t => t.id === action.payload.taskId);
            if (taskIndex !== -1) {
              group.tasks.splice(taskIndex, 1);
            }
          });
        }
      })

      /**
       * 移动任务成功的状态处理
       * 服务器返回更新后的完整项目数据，直接替换当前项目
       */
      .addCase(moveTask.fulfilled, (state, action) => {
        if (state.currentProject && state.currentProject.id === action.payload.id) {
          state.currentProject = action.payload;
        }
        // 替换项目列表中的该项目
        const idx = state.projects.findIndex(p => p.id === action.payload.id);
        if (idx !== -1) {
          state.projects[idx] = action.payload;
        }
      })

      /**
       * 移动任务失败的状态处理
       * 需要回滚乐观更新的状态
       */
      .addCase(moveTask.rejected, (state, action) => {
        console.error('移动任务失败:', action.error);
        state.error = action.error.message || 'Failed to move task';
        // TODO: 实现乐观更新的回滚逻辑
      })

      /**
       * 创建分组成功的状态处理
       * 将新分组添加到当前项目的分组列表中
       */
      .addCase(createGroup.fulfilled, (state, action) => {
        if (state.currentProject) {
          state.currentProject.groups.push(action.payload);
        }
        // 同步项目列表
        const projectIdArg = (action.meta as any)?.arg?.projectId as string | undefined;
        if (projectIdArg) {
          const proj = state.projects.find(p => p.id === projectIdArg);
          if (proj) {
            proj.groups.push(action.payload);
          }
        }
      })

      /**
       * 更新分组成功的状态处理
       * 找到对应的分组并更新其数据（如名称、颜色等）
       */
      .addCase(updateGroup.fulfilled, (state, action) => {
        if (state.currentProject) {
          const index = state.currentProject.groups.findIndex(g => g.id === action.payload.id);
          if (index !== -1) {
            state.currentProject.groups[index] = action.payload;
          }
        }
        // 同步项目列表
        const projectIdArg = (action.meta as any)?.arg?.projectId as string | undefined;
        if (projectIdArg) {
          const proj = state.projects.find(p => p.id === projectIdArg);
          if (proj) {
            const index = proj.groups.findIndex(g => g.id === action.payload.id);
            if (index !== -1) {
              proj.groups[index] = action.payload;
            }
          }
        }
      })

      /**
       * 删除分组成功的状态处理
       * 从当前项目中移除指定的分组
       * 注意：分组内的任务在服务器端已经被移动到其他分组
       */
      .addCase(deleteGroup.fulfilled, (state, action) => {
        if (state.currentProject) {
          const index = state.currentProject.groups.findIndex(g => g.id === action.payload.groupId);
          if (index !== -1) {
            state.currentProject.groups.splice(index, 1);
          }
        }
        // 同步项目列表
        const proj = state.projects.find(p => p.id === action.payload.projectId);
        if (proj) {
          const index = proj.groups.findIndex(g => g.id === action.payload.groupId);
          if (index !== -1) {
            proj.groups.splice(index, 1);
          }
        }
      });
  },
});

/**
 * ===== 导出的 Action 创建函数 =====
 * 这些函数用于在组件中触发状态更新
 * 使用方式：dispatch(setFilters({status: ['in_progress']}))
 */
export const {
  /** 设置筛选条件的 action 创建函数 */
  setFilters,
  /** 设置排序方式的 action 创建函数 */
  setSort,
  /** 切换视图模式的 action 创建函数 */
  setViewMode,
  /** 清除错误信息的 action 创建函数 */
  clearError,
  /** 本地更新任务状态的 action 创建函数（用于乐观更新） */
  updateTaskLocal,
  /** 本地移动任务的 action 创建函数（用于拖拽的乐观更新） */
  moveTaskLocal,
} = projectSlice.actions;

/**
 * 导出项目管理的 reducer
 * 这个 reducer 会被注册到 Redux store 中，处理所有项目相关的状态更新
 */
export default projectSlice.reducer;
